<?php
/**
 * 描述 : user center 核心 API
 * 作者 : Edgar.lee
 */
class uc_api_api {

    /**
     * 描述 : 连接测试
     * 作者 : Edgar.lee
     */
    public static function test() {
        if( empty(uc::$config['url']) ) {                                                                               //本地连接
            $temp = uc_com_face::_sql('SELECT TRUE');
            return isset($temp[0]);
        } else {                                                                                                        //远程验证
            return uc::_exec(array(                                                                                     //此处会因为服务端配置导致死循环(没时间)
                    'call'   => 'test',
                    'params' => array()
                ));
        }
    }

    /**
     * 描述 : 登录用户名
     * 参数 :
     *      name : 用户名,''=同步退出,字符串=同步登入
     *      pwd  : 登录时指定密码
     * 返回 :
     *      返回同步登入的html脚步
     * 作者 : Edgar.lee
     */
    public static function &login($name = '', $pwd = '') {
        $data = uc::_exec(array(
                'call'   => 'login_',
                'params' => array($name, $pwd)
            ));

        if( $data ) {                                                                                                   //数据读取成功
            foreach($data as &$v) {
                $v = "<iframe src='{$v}' style='display:none;'></iframe>";
            }
            $data = join($data);
        }

        return $data;
    }

    /**
     * 描述 : 权限验证
     * 参数 :
     *      name : 用户名
     * 作者 : Edgar.lee
     */
    public static function &check($name, $url, $get = array(), &$post = array()) {
        $result = true;

        if( !$index = &$_SESSION['uc_api_api']['check'][$name] ) {                                                      //无权访问的路径
            $temp = uc::_exec(array(
                    'call'   => 'check_',
                    'params' => array($name, uc::$config['id'])
                ));

            foreach($temp as &$v) {
                $index[$v['path']][] = json_decode($v['match'], true);
            }
        }

        if( isset($index[$url]) ) {
            foreach($index[$url] as &$v) {
                if( self::match($v['G'], $get) && self::match($v['P'], $post) ) {
                    $result = false;
                    break ;
                }
            }
        }

        return $result;
    }

    /**
     * 描述 : 属性设置
     * 参数 :
     *      name  : 用户名称
     *      value :
     *          字符串 : 读取当前应用属性,用","分隔,如:'email,tel'
     *          数  组 : 读取或设置指定属性,结构如下
     *              操作当前应用属性 : {
     *                  属性键 : true=读取,字符串=设置
     *              }
     *              操作其它应用属性 : {
     *                  应用ID : "字符串格式化" 或与 "操作当前应用属性" 结构相同
     *              }
     * 返回 :
     *      返回一个数组,对应操作失败的属性值为false
     * 作者 : Edgar.lee
     */
    public static function &attr($name, $value, $type = false) {
        $index = &$_SESSION['uc_api_api']['attr'][$name];                                                               //属性引用
        $data = null;                                                                                                   //准备读取的数据

        if( is_string($value) || !is_int(key($value)) ) {                                                               //转成当前数组
            $value = array(uc::$config['id'] => $value);
        }

        foreach($value as $ka => &$va) {                                                                                //应用ID => 读取属性
            is_string($va) && $va = array_fill_keys(explode(',', $va), true);                                           //字符串属性解析

            foreach($va as $k => &$v) {
                $type && $data[$ka][$k] = true;                                                                         //强制查询数据

                if( $v === true ) {                                                                                     //读取属性
                    if( isset($index[$ka][$k]) ) {                                                                      //数据[应用键][属性名]
                        $v = $index[$ka][$k];
                        continue;
                    }
                }

                $data[$ka][$k] = &$v;                                                                                   //生成操作列表
            }
        }

        if( $data !== null ) {                                                                                          //处理操作信息
            $temp = uc::_exec(array(
                    'call'   => 'attr_',
                    'params' => array($name, &$data, $type)
                ));

            $type ? $index = &$temp['data'] : $index = &$temp;                                                          //引用遍历数据
            foreach($index as $ka => &$va) {                                                                            //保存被得到的信息
                foreach($va as $k => &$v) {
                    $index[$ka][$k] = &$v;
                    $value[$ka][$k] = $v === null ? false : $v;
                }
            }
            $type && $value = array('attr' => &$temp['attr'], 'data' => $value);
        }
        return $value;
    }

    /**
     * 描述 : 同步登录脚步
     * 作者 : Edgar.lee
     */
    protected static function &login_($name, $pwd) {
        $cofig = &uc::$config;                                                                                          //引用配置文件
        $data = true;

        if( $pwd ) {
            $sql = "SELECT 
                1 c
            FROM 
                `uc_user` 
            WHERE
                `name` = '{$name}'
            AND `pwd` = PASSWORD('{$pwd}')
            LIMIT 1";
            $data = uc_com_face::_sql($sql);
            $data = isset($data[0]);
        }

        if( $data ) {
            $timeout = $cofig['timeout'] + $_SERVER['REQUEST_TIME'];
            $params = array('call' => 'login', 'params' => array(&$name));
            $params = uc::_coding($params, true);
            $data = array();

            $sql = 'SELECT
                `id`, `key`, `bind`
            FROM
                `uc_appList`
            WHERE
                `sync` = "on"';
            $temp = uc_com_face::_sql($sql);

            foreach($temp as &$v) {
                $v['bind'] = json_decode($v['bind']);

                foreach($v['bind'] as &$vb) {
                    $data[] = $vb . '/api/oi.php?' . http_build_query(array(
                                'id'   => $v['id'],
                                'to'   => $timeout,
                                'md5'  => md5($v['id'] . $v['key'] . $timeout),
                                'data' => &$params
                            ));
                }
            }
        }

        return $data;
    }

    /**
     * 描述 : 获取指定用户的功能权限
     * 参数 :
     *      name  : 用户名
     *      appId : 应用ID
     * 作者 : Edgar.lee
     */
    protected static function &check_($name, $appId) {
        $sql = "SELECT
            `uc_funcList`.id
        FROM
            `uc_user`
                LEFT JOIN `uc_userRole` ON
                    `uc_userRole`.`userId` = `uc_user`.id
                LEFT JOIN `uc_roleData` ON
                    `uc_roleData`.roleId = `uc_userRole`.roleId
                AND `uc_roleData`.appId = '{$appId}'
                LEFT JOIN `uc_funcList` ON
                    `uc_funcList`.id = `uc_roleData`.funcId
        WHERE
            `uc_user`.name = '{$name}'
        AND `uc_funcList`.id IS NOT NULL";                                                                              //用户在应用中的权限

        $sql = "SELECT
            `uc_funcList`.path, `uc_funcList`.`match`
        FROM
            `uc_funcList`
        WHERE
            `uc_funcList`.appId = '{$appId}'
        AND `uc_funcList`.id NOT IN ({$sql})";                                                                          //用户没有权限的功能ID

        $index = &uc_com_face::_sql($sql);
        return $index;
    }

    /**
     * 描述 : 操作属性
     * 参数 :
     *      name : 用户名
     *      data : 需操作的属性, 格式如下 {
     *          应用键 : {
     *              属性键 : true=读取属性, 字符串=写入数据
     *          }
     *      }
     * 返回 :
     *      处理后的数组, 对应属性键操作失败的值为false
     * 作者 : Edgar.lee
     */
    protected static function &attr_($name, $data, $type) {
        $config = &uc::$config;                                                                                         //引用配置
        $attrData = array();                                                                                            //属性数据
        $type = $type ? '`uc_attrList`.data,' : '';

        foreach($data as $ka => &$va) {                                                                                 //应用键 => 操作属性
            $mode = array();                                                                                            //属性权限{属性键 : 权限值}

            $sql = join('","', array_keys($va)) ;
            $sql = "SELECT
                {$type}
                `uc_attrMode`.chmod mode,                                       /*属性权限*/
                `user`.id uId,                                                  /*用户ID*/
                `uc_attrList`.id aId,                                           /*属性ID*/
                `uc_attrList`.`key`,                                            /*属性键*/
                IFNULL(`uc_attrVal`.`value`, `uc_attrList`.default) `val`,      /*属性值*/
                IFNULL(`uc_attrVal`.id, 'NULL') vId                             /*属性值ID*/
            FROM
                `uc_attrMode`
                    LEFT JOIN (SELECT
                            id
                        FROM
                            `uc_user`
                        WHERE
                            `name` = '{$name}') `user` ON TRUE
                    LEFT JOIN `uc_attrList` ON
                        `uc_attrList`.id = `uc_attrMode`.attrId
                    LEFT JOIN `uc_attrVal` ON
                        `uc_attrVal`.userId = `user`.id
                    AND `uc_attrVal`.attrId = `uc_attrList`.id
            WHERE
                `user`.id IS NOT NULL
            AND `uc_attrMode`.appId = '{$config['id']}'
            AND `uc_attrMode`.attrAppId = '{$ka}'
            AND `uc_attrList`.key IN (\"{$sql}\")";                                                                     //此处三期要把数据缓存出来
            $temp = uc_com_face::_sql($sql);

            foreach($temp as &$v) {
                $mode[$v['key']] = &$v;
                $attrData[$ka][$v['key']] = array(
                    'mode' => &$v['mode'],
                    'data' => &$v['data']
                );
            }

            foreach($va as $k => &$v) {                                                                                 //属性键 => 属性值
                if( empty($mode[$k]) ) {                                                                                //无操作权限
                    $v = false;
                } else if( $v === true ) {                                                                              //读取数据
                    $v = $mode[$k]['mode'] & 4 ? $mode[$k]['val'] : false;                                              //读取权限 ? 读取 : 失败
                } else if( $mode[$k]['mode'] & 2 ) {                                                                    //设置数据权限
                    $sql = "INSERT INTO `uc_attrVal` (
                        `id`, `userId`, `appId`, `attrId`, `value`
                    ) VALUES (
                        {$mode[$k]['vId']}, '{$mode[$k]['uId']}', '{$ka}', '{$mode[$k]['aId']}', '{$v}'
                    ) ON DUPLICATE KEY UPDATE 
                        `value` = '{$v}'";
                    uc_com_face::_sql($sql);                                                                            //修改数据
                } else {                                                                                                //无设置权限
                    $v = null;
                }
            }
        }

        if( $type ) {
            $type = array('attr' => &$attrData, 'data' => &$data);
        } else {
            $type = &$data;
        }
        return $type;
    }

    /**
     * 描述 : 权限细节对比
     * 作者 : Edgar.lee
     */
    private static function match(&$match, &$params) {
        foreach($match['E'] as $k => &$v) {                                                                             //排除,发现一个匹配时返回false
            if( isset($params[$k]) && ($v === '' || $params[$k] === $v) ) {
                return false;
            }
        }

        foreach($match['C'] as $k => &$v) {                                                                             //包含,发现一个不匹配时返回false
            if( !isset($params[$k]) || ($v !== '' && $params[$k] !== $v) ) {
                return false;
            }
        }

        return true;                                                                                                    //匹配
    }
}